﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Text;

namespace Dotnet.Code.Extend
{
    public enum ThumbnailMode
    {
        /// <summary>
        /// 宽高缩放模式,可能变形
        /// </summary>
        UsrHeightWidth,
        UsrHeightWidthBound,
        /// <summary>
        /// 指定宽度,高按比例
        /// </summary>
        UsrWidth,
        /// <summary>
        /// 指定宽（过小则不变），高按比例
        /// </summary>
        UsrWidthBound,
        /// <summary>
        /// 自定高度,宽按比例
        /// </summary>
        UsrHeight,
        /// <summary>
        /// 指定高(过小则不变),宽按比例
        /// </summary>
        UsrHeightBound,
        /// <summary>
        /// 剪切
        /// </summary>
        Cut,
        NONE
    }

    public static partial class Ext
    {/// <summary>
     /// 制作图片的缩略图
     /// </summary>
     /// <param name="originalImage">原图</param>
     /// <param name="width">指定的宽度</param>
     /// <param name="height">指定的高度</param>
     /// <param name="mode">指定的模式</param>
     /// <remarks>
     ///     <paramref name="mode">
     ///         <para>ThumbnailMode.UsrHeightWidth:指定高宽缩放（可能变形）</para>
     ///         <para>ThumbnailMode.UsrHeightWidthBound:指定高宽缩放（可能变形,过小则不变）</para>
     ///         <para>ThumbnailMode.UsrWidth:指定宽，高按比例</para>
     ///         <para>ThumbnailMode.UsrWidthBound:指定宽（过小则不变），高按比例</para>
     ///         <para>ThumbnailMode.UsrHeight:指定高，宽按比例</para>
     ///         <para>ThumbnailMode.UsrHeightBound:指定高（过小则不变,宽按比例)</para>
     ///     </paramref>
     /// </remarks>
     /// <returns></retCut,urns>
        public static Image MakeThumbnail(this Image originalImage, int width, int height, ThumbnailMode mode)
        {
            int towidth = width;
            int toheight = height;

            int x = 0;
            int y = 0;
            int initWidth = originalImage.Width;
            int initHeight = originalImage.Height;


            switch (mode)
            {
                case ThumbnailMode.UsrHeightWidth: //指定高宽缩放（可能变形）
                    break;
                case ThumbnailMode.UsrHeightWidthBound: //指定高宽缩放（可能变形）（过小则不变）
                    if (originalImage.Width <= width && originalImage.Height <= height)
                    {
                        return originalImage;
                    }
                    if (originalImage.Width < width)
                    {
                        towidth = originalImage.Width;
                    }
                    if (originalImage.Height < height)
                    {
                        toheight = originalImage.Height;
                    }
                    break;
                case ThumbnailMode.UsrWidth: //指定宽，高按比例
                    toheight = originalImage.Height * width / originalImage.Width;
                    break;
                case ThumbnailMode.UsrWidthBound: //指定宽（过小则不变），高按比例
                    if (originalImage.Width <= width)
                    {
                        return originalImage;
                    }
                    else
                    {
                        toheight = originalImage.Height * width / originalImage.Width;
                    }
                    break;
                case ThumbnailMode.UsrHeight: //指定高，宽按比例
                    towidth = originalImage.Width * height / originalImage.Height;
                    break;
                case ThumbnailMode.UsrHeightBound: //指定高（过小则不变），宽按比例
                    if (originalImage.Height <= height)
                    {
                        return originalImage;
                    }
                    else
                    {
                        towidth = originalImage.Width * height / originalImage.Height;
                    }
                    break;
                case ThumbnailMode.Cut: //指定高宽裁减（不变形）
                    //计算宽高比
                    double srcScale = (double)originalImage.Width / (double)originalImage.Height;
                    double destScale = (double)towidth / (double)toheight;
                    //宽高比相同
                    if (srcScale - destScale >= 0 && srcScale - destScale <= 0.001)
                    {
                        x = 0;
                        y = 0;
                        initWidth = originalImage.Width;
                        initHeight = originalImage.Height;
                    }
                    //源宽高比大于目标宽高比
                    //(源的宽比目标的宽大)
                    else if (srcScale > destScale)
                    {
                        initWidth = originalImage.Height * towidth / toheight;
                        initHeight = originalImage.Height;
                        x = (originalImage.Width - initWidth) / 2;
                        y = 0;
                    }
                    //源宽高比小于目标宽高小，源的高度大于目标的高度
                    else
                    {
                        initWidth = originalImage.Width;
                        initHeight = originalImage.Width * height / towidth;
                        x = 0;
                        y = (originalImage.Height - initHeight) / 2;
                    }
                    break;
                default:
                    break;
            }
            Image bitmap = new Bitmap(towidth, toheight);
            //新建一个画板
            using (Graphics g = Graphics.FromImage(bitmap))
            {
                //设置高质量插值法
                g.CompositingQuality = CompositingQuality.HighQuality;
                //设置高质量,低速段呈现的平滑程度
                g.SmoothingMode = SmoothingMode.HighQuality;

                //在指定的位置上,并按指定大小绘制原图片的指定部分
                g.DrawImage(originalImage, new Rectangle(0, 0, towidth, toheight), new Rectangle(x, y, initWidth, initHeight), GraphicsUnit.Pixel);
            }
            return bitmap;
        }

        public static Image MakeThumbnail(Stream originalStream, int width, int height, ThumbnailMode mode)
        {
            Image originalImage = Image.FromStream(originalStream);
            try
            {
                return MakeThumbnail(originalImage, width, height, mode);
            }
            catch (Exception)
            {
                originalStream.Dispose();
                return null;
            }
        }

        public static void MakeThumbnail(Image originalImage, string savePath, int width, int height, ThumbnailMode mode)
        {
            Image image = MakeThumbnail(originalImage, width, height, mode);
            try
            {
                image.Save(savePath);
            }
            catch (Exception)
            {
                image.Dispose();
            }
        }

        public static void MakeThumbnail(string originalImagePath, string savePath, int width, int height, ThumbnailMode mode)
        {
            Image image = Image.FromFile(originalImagePath);
            try
            {
                MakeThumbnail(image, savePath, width, height, mode);
            }
            catch (Exception)
            {
                image.Dispose();
            }
        }
        /// <summary>
        /// 从大图中截取一部分图片
        /// </summary>
        /// <param name="fromImagePath">来源图片地址</param>        
        /// <param name="offsetX">从偏移X坐标位置开始截取</param>
        /// <param name="offsetY">从偏移Y坐标位置开始截取</param>
        /// <param name="toImagePath">保存图片地址</param>
        /// <param name="width">保存图片的宽度</param>
        /// <param name="height">保存图片的高度</param>
        /// <returns></returns>
        public static Image CaptureImage(this Image fromImage, int offsetX, int offsetY, int width, int height)
        {
            //原图片文件
            //Image fromImage = Image.FromFile(fromImagePath);
            //创建新图位图
            Bitmap bitmap = new Bitmap(width, height);
            //创建作图区域
            Graphics graphic = Graphics.FromImage(bitmap);
            //截取原图相应区域写入作图区
            graphic.DrawImage(fromImage, 0, 0, new Rectangle(offsetX, offsetY, width, height), GraphicsUnit.Pixel);
            //从作图区生成新图
            Image saveImage = Image.FromHbitmap(bitmap.GetHbitmap());
            //保存图片
           // saveImage.Save(toImagePath, ImageFormat.Png);
            //释放资源   
            //saveImage.Dispose();
            graphic.Dispose();
            bitmap.Dispose();
            return saveImage;
        }


        private static void GetThumbnail1(Image serverImage, ref System.IO.MemoryStream ms, int width, int height)
        {
            //System.Drawing.Image serverImage = System.Drawing.Image.FromFile(serverImagePath);
            // string thumbnailImagePath= string.Format("D:\\{0}.jpg", DateTime.Now.ToString("yyyyMMddHHmmssfff"));
            //画板大小
            int towidth = width;
            int toheight = height;
            //缩略图矩形框的像素点
            int x = 0;
            int y = 0;
            int ow = serverImage.Width;
            int oh = serverImage.Height;

            if (ow > oh)
            {
                toheight = serverImage.Height * width / serverImage.Width;
            }
            else
            {
                towidth = serverImage.Width * height / serverImage.Height;
            }
            //新建一个bmp图片
            System.Drawing.Image bm = new System.Drawing.Bitmap(width, height);
            //新建一个画板
            System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(bm);
            //设置高质量插值法
            g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;
            //设置高质量,低速度呈现平滑程度
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
            //清空画布并以透明背景色填充
            g.Clear(System.Drawing.Color.White);
            //在指定位置并且按指定大小绘制原图片的指定部分
            g.DrawImage(serverImage, new System.Drawing.Rectangle((width - towidth) / 2, (height - toheight) / 2, towidth, toheight),
                0, 0, ow, oh,
                System.Drawing.GraphicsUnit.Pixel);
            try
            {
                bm.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
                //以jpg格式保存缩略图
                //bm.Save(thumbnailImagePath, System.Drawing.Imaging.ImageFormat.Jpeg);
            }
            catch (System.Exception e)
            {
                throw e;
            }
            finally
            {
                serverImage.Dispose();
                bm.Dispose();
                g.Dispose();
            }
        }
        public static Image MakeThumbnail(this Image image, int width)
        {
            int height = (width * image.Height / image.Width);
            System.IO.MemoryStream ms = new System.IO.MemoryStream();
            GetThumbnail1(image, ref ms, width, height);
            return Image.FromStream(ms);
        }
        /// <summary>
        /// 生成缩略图
        /// </summary>
        /// <param name="originalImagePath">源路径</param>
        /// <param name="thumbnailPath">目标路径</param>
        /// <param name="width">宽</param>
        /// <param name="height">高</param>
        /// <param name="mode">缩略模式</param>
        public static Image MakeThumbnail(this Image originalImage, int width, int height, string mode = "Cut")
        {
            int towidth = width;
            int toheight = height;

            int x = 0;
            int y = 0;
            int ow = originalImage.Width;
            int oh = originalImage.Height;

            switch (mode)
            {
                case "HW"://指定高宽缩放（可能变形）                
                    break;
                case "W"://指定宽，高按比例                    
                    toheight = originalImage.Height * width / originalImage.Width;
                    break;
                case "H"://指定高，宽按比例
                    towidth = originalImage.Width * height / originalImage.Height;
                    break;
                case "Cut"://指定高宽裁减（不变形）                
                    if ((double)originalImage.Width / (double)originalImage.Height > (double)towidth / (double)toheight)
                    {
                        oh = originalImage.Height;
                        ow = originalImage.Height * towidth / toheight;
                        y = 0;
                        x = (originalImage.Width - ow) / 2;
                    }
                    else
                    {
                        ow = originalImage.Width;
                        oh = originalImage.Width * height / towidth;
                        x = 0;
                        y = (originalImage.Height - oh) / 2;
                    }
                    break;
                default:
                    break;
            }

            //新建一个bmp图片
            Bitmap bitmap = new System.Drawing.Bitmap(towidth, toheight);
            //设置其生成图片的dpi
            bitmap.SetResolution(originalImage.HorizontalResolution, originalImage.VerticalResolution);

            //新建一个画板
            Graphics g = GetGraphics(bitmap);

            //清空画布并以透明背景色填充
            g.Clear(Color.White);

            //在指定位置并且按指定大小绘制原图片的指定部分
            g.DrawImage(originalImage, new Rectangle(0, 0, towidth, toheight),
                new Rectangle(x, y, ow, oh),
                GraphicsUnit.Pixel);
            return bitmap;
        }
        /// <summary>
        /// 获取高清的Graphics
        /// </summary>
        /// <param name="img"></param>
        /// <returns></returns>
        private static Graphics GetGraphics(Image img)
        {
            var g = Graphics.FromImage(img);
            //设置质量
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
            g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
            //InterpolationMode不能使用High或者HighQualityBicubic,如果是灰色或者部分浅色的图像是会在边缘处出一白色透明的线
            //用HighQualityBilinear却会使图片比其他两种模式模糊（需要肉眼仔细对比才可以看出）
            g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Default;
            g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
            return g;
        }
        private static void SaveToDisk(this Image img,string fileName)
        {
            //FileStream stream=img
           // return;
        }
        public static byte[] ToBytes(this Image img)
        {
            using (MemoryStream stream = new MemoryStream())
            {
                img.Save(stream, ImageFormat.Jpeg);
                byte[] data = new byte[stream.Length];
                stream.Seek(0, SeekOrigin.Begin);
                stream.Read(data, 0, Convert.ToInt32(stream.Length));
                return data;
            }
        }

        //public static byte[] BitmapToByte(this Bitmap bitmap)
        //{
        //    using (MemoryStream stream = new MemoryStream())
        //    {
        //        bitmap.Save(stream, ImageFormat.Jpeg);
        //        byte[] data = new byte[stream.Length];
        //        stream.Seek(0, SeekOrigin.Begin);
        //        stream.Read(data, 0, Convert.ToInt32(stream.Length));
        //        return data;
        //    }
        //}
    }
}
